package zilvic.game.room.tile;

import java.awt.Graphics;
import org.duncan.Math2D.Point2D;
import org.duncan.Math2D.Rect2D;
import zilvic.game.Game;
import zilvic.game.room.Room;
import zilvic.game.room.entity.actor.Actor;
import zilvic.resources.ByteMagic;
import zilvic.resources.Parsable;
import zilvic.resources.sprites.Sprite;
import zilvic.resources.sprites.SpriteStore;

/**
 *
 * @author Duncan
 */
public class Tile implements Parsable {
    private Sprite[] layers              = new Sprite[3];
    private boolean solid                = false;
    private Point2D position;

    public Tile(Point2D position) {
        this.position = position;
    }

    public Tile setLayer(byte layer, Sprite sprite) {
        layers[layer] = sprite;
        return this;
    }

    public Sprite getLayer(byte layer) {
        return layers[layer];
    }

    public Tile setPosition(Point2D position) {
        this.position = position;
        return this;
    }

    public Point2D getPosition() {
        return position;
    }

    public Tile setSolid(boolean solid) {
        this.solid = solid;
        return this;
    }

    public boolean isSolid() {
        return solid;
    }

    public void render(Graphics floor, Graphics walls, Graphics roof) {
        layers[Room.LAYER_FLOOR].draw(floor, getPosition(), (byte) 0, Actor.DIRECTION_DOWN);
        layers[Room.LAYER_WALLS].draw(walls, getPosition(), (byte) 0, Actor.DIRECTION_DOWN);
        layers[Room.LAYER_ROOF].draw(roof, getPosition(), (byte) 0, Actor.DIRECTION_DOWN);
    }

    public boolean contains(Point2D position) {
        return (new Rect2D(this.position, this.position.clone().add(
                new Point2D(Game.GRID_SIZE, Game.GRID_SIZE))).contains(position));
    }

    /**
     * Returns a compressed byte representation of this tile. Use the following
     * method to uncompress it: ByteMagic.uncompressBytes(); The result will be
     * as following:
     * 0. The floor-layer.
     * 1. The walls-layer.
     * 2. The roof-layer.
     * 3. A single boolean that is true if this tile is solid.
     * 4. The position of this tile.
     * @return Bytes containing all the information in this.
     */
    public byte[] toBytes() {
        return ByteMagic.compressBytes(new byte[][] {
            layers[Room.LAYER_FLOOR].getName().getBytes(),
            layers[Room.LAYER_WALLS].getName().getBytes(),
            layers[Room.LAYER_ROOF].getName().getBytes(),
            ByteMagic.booleanToBytes(solid),
            position.toBytes()});
    }

    public void fromBytes(byte[] bytes) {
        byte[][] u = ByteMagic.uncompressBytes(bytes);
        layers[Room.LAYER_FLOOR] = SpriteStore.get().getSprite(ByteMagic.bytesToString(u[0]));
        layers[Room.LAYER_WALLS] = SpriteStore.get().getSprite(ByteMagic.bytesToString(u[1]));
        layers[Room.LAYER_ROOF]  = SpriteStore.get().getSprite(ByteMagic.bytesToString(u[2]));
        solid                    = ByteMagic.bytesToBoolean(u[3]);
        position                 = new Point2D(0, 0);
        position.fromBytes(u[4]);
    }
}
